# uncompyle6 version 3.2.3
# Python bytecode 3.6 (3379)
# Decompiled from: Python 3.6.8 |Anaconda custom (64-bit)| (default, Feb 21 2019, 18:30:04) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: site-packages\gevent\_socket3.py
"""
Python 3 socket module.
"""
from __future__ import absolute_import
import io, os, sys, time
from gevent import _socketcommon
from gevent._util import copy_globals
from gevent._compat import PYPY
import _socket
from os import dup

copy_globals(
    _socketcommon,
    globals(),
    names_to_ignore=_socketcommon.__extensions__,
    dunder_names_to_keep=(),
)
__socket__ = _socketcommon.__socket__
__implements__ = _socketcommon._implements
__extensions__ = _socketcommon.__extensions__
__imports__ = _socketcommon.__imports__
__dns__ = _socketcommon.__dns__
SocketIO = __socket__.SocketIO


def _get_memory(data):
    mv = memoryview(data)
    if mv.shape:
        return mv
    else:
        return mv.tobytes()


timeout_default = object()


class _wrefsocket(_socket.socket):
    __slots__ = ("__weakref__",)
    if PYPY:
        timeout = property(lambda s: s.gettimeout(), lambda s, nv: s.settimeout(nv))


class socket(object):
    """
    gevent `socket.socket <https://docs.python.org/3/library/socket.html#socket-objects>`_
    for Python 3.
    
    This object should have the same API as the standard library socket linked to above. Not all
    methods are specifically documented here; when they are they may point out a difference
    to be aware of or may document a method the standard library does not.
    """

    _gevent_sock_class = _wrefsocket

    def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None):
        self._sock = self._gevent_sock_class(family, type, proto, fileno)
        self._io_refs = 0
        self._closed = False
        _socket.socket.setblocking(self._sock, False)
        fileno = _socket.socket.fileno(self._sock)
        self.hub = get_hub()
        io_class = self.hub.loop.io
        self._read_event = io_class(fileno, 1)
        self._write_event = io_class(fileno, 2)
        self.timeout = _socket.getdefaulttimeout()

    def __getattr__(self, name):
        return getattr(self._sock, name)

    if hasattr(_socket, "SOCK_NONBLOCK"):

        @property
        def type(self):
            if self.timeout != 0.0:
                return self._sock.type & ~_socket.SOCK_NONBLOCK
            else:
                return self._sock.type

    def __enter__(self):
        return self

    def __exit__(self, *args):
        if not self._closed:
            self.close()

    def __repr__(self):
        """Wrap __repr__() to reveal the real class name."""
        try:
            s = _socket.socket.__repr__(self._sock)
        except Exception as ex:
            s = "<socket [%r]>" % ex

        if s.startswith("<socket object"):
            s = "<%s.%s%s%s" % (
                self.__class__.__module__,
                self.__class__.__name__,
                getattr(self, "_closed", False) and " [closed] " or "",
                s[7:],
            )
        return s

    def __getstate__(self):
        raise TypeError("Cannot serialize socket object")

    def _get_ref(self):
        return self._read_event.ref or self._write_event.ref

    def _set_ref(self, value):
        self._read_event.ref = value
        self._write_event.ref = value

    ref = property(_get_ref, _set_ref)

    def _wait(self, watcher, timeout_exc=timeout("timed out")):
        """Block the current greenlet until *watcher* has pending events.
        
        If *timeout* is non-negative, then *timeout_exc* is raised after *timeout* second has passed.
        By default *timeout_exc* is ``socket.timeout('timed out')``.
        
        If :func:`cancel_wait` is called, raise ``socket.error(EBADF, 'File descriptor was closed in another greenlet')``.
        """
        if watcher.callback is not None:
            raise _socketcommon.ConcurrentObjectUseError(
                "This socket is already used by another greenlet: %r"
                % (watcher.callback,)
            )
        if self.timeout is not None:
            timeout = Timeout.start_new(self.timeout, timeout_exc, ref=False)
        else:
            timeout = None
        try:
            self.hub.wait(watcher)
        finally:
            if timeout is not None:
                timeout.cancel()

    def dup(self):
        """dup() -> socket object
        
        Return a new socket object connected to the same system resource.
        """
        fd = dup(self.fileno())
        sock = self.__class__(self.family, self.type, self.proto, fileno=fd)
        sock.settimeout(self.gettimeout())
        return sock

    def accept(self):
        """accept() -> (socket object, address info)
        
        Wait for an incoming connection.  Return a new socket
        representing the connection, and the address of the client.
        For IP sockets, the address info is a pair (hostaddr, port).
        """
        while True:
            try:
                fd, addr = self._accept()
                break
            except BlockingIOError:
                if self.timeout == 0.0:
                    raise

            self._wait(self._read_event)

        sock = socket(self.family, self.type, self.proto, fileno=fd)
        if getdefaulttimeout() is None:
            if self.gettimeout():
                sock.setblocking(True)
        return (sock, addr)

    def makefile(
        self, mode="r", buffering=None, *, encoding=None, errors=None, newline=None
    ):
        """Return an I/O stream connected to the socket
        
        The arguments are as for io.open() after the filename,
        except the only mode characters supported are 'r', 'w' and 'b'.
        The semantics are similar too.
        """
        for c in mode:
            if c not in frozenset({"b", "w", "r"}):
                raise ValueError("invalid mode %r (only r, w, b allowed)")

        writing = "w" in mode
        reading = "r" in mode or not writing
        if not reading:
            if not writing:
                raise AssertionError
        binary = "b" in mode
        rawmode = ""
        if reading:
            rawmode += "r"
        if writing:
            rawmode += "w"
        raw = SocketIO(self, rawmode)
        self._io_refs += 1
        if buffering is None:
            buffering = -1
        if buffering < 0:
            buffering = io.DEFAULT_BUFFER_SIZE
        if buffering == 0:
            if not binary:
                raise ValueError("unbuffered streams must be binary")
            return raw
        else:
            if reading:
                if writing:
                    buffer = io.BufferedRWPair(raw, raw, buffering)
                if reading:
                    buffer = io.BufferedReader(raw, buffering)
                else:
                    if not writing:
                        raise AssertionError
                    buffer = io.BufferedWriter(raw, buffering)
                if binary:
                    return buffer
                text = io.TextIOWrapper(buffer, encoding, errors, newline)
                text.mode = mode
            return text

    def _decref_socketios(self):
        if self._io_refs > 0:
            self._io_refs -= 1
        if self._closed:
            self.close()

    def _real_close(self, _ss=_socket.socket, cancel_wait_ex=cancel_wait_ex):
        self.hub.cancel_wait(self._read_event, cancel_wait_ex)
        self.hub.cancel_wait(self._write_event, cancel_wait_ex)
        _ss.close(self._sock)
        try:
            self._sock = self._gevent_sock_class(self.family, self.type, self.proto)
        except OSError:
            pass
        else:
            _ss.close(self._sock)

    def close(self):
        self._closed = True
        if self._io_refs <= 0:
            self._real_close()

    @property
    def closed(self):
        return self._closed

    def detach(self):
        """detach() -> file descriptor
        
        Close the socket object without closing the underlying file descriptor.
        The object cannot be used after this call, but the file descriptor
        can be reused for other purposes.  The file descriptor is returned.
        """
        self._closed = True
        return self._sock.detach()

    def connect(self, address):
        if self.timeout == 0.0:
            return _socket.socket.connect(self._sock, address)
        if isinstance(address, tuple):
            r = getaddrinfo(address[0], address[1], self.family)
            address = r[0][-1]
        if self.timeout is not None:
            timer = Timeout.start_new(self.timeout, timeout("timed out"))
        else:
            timer = None
        try:
            while True:
                err = self.getsockopt(SOL_SOCKET, SO_ERROR)
                if err:
                    raise error(err, strerror(err))
                result = _socket.socket.connect_ex(self._sock, address)
                if not result or result == EISCONN:
                    break
                elif (
                    result in (EWOULDBLOCK, EINPROGRESS, EALREADY)
                    or result == EINVAL
                    and is_windows
                ):
                    self._wait(self._write_event)
                else:
                    raise error(result, strerror(result))

        finally:
            if timer is not None:
                timer.cancel()

    def connect_ex(self, address):
        try:
            return self.connect(address) or 0
        except timeout:
            return EAGAIN
        except gaierror:
            raise
        except error as ex:
            if ex.errno:
                return ex.errno
            raise

    def recv(self, *args):
        while True:
            try:
                return _socket.socket.recv(self._sock, *args)
            except error as ex:
                if ex.args[0] != EWOULDBLOCK or self.timeout == 0.0:
                    raise

            self._wait(self._read_event)

    if hasattr(_socket.socket, "sendmsg"):

        def recvmsg(self, *args):
            while True:
                try:
                    return _socket.socket.recvmsg(self._sock, *args)
                except error as ex:
                    if ex.args[0] != EWOULDBLOCK or self.timeout == 0.0:
                        raise

                self._wait(self._read_event)

        def recvmsg_into(self, *args):
            while True:
                try:
                    return _socket.socket.recvmsg_into(self._sock, *args)
                except error as ex:
                    if ex.args[0] != EWOULDBLOCK or self.timeout == 0.0:
                        raise

                self._wait(self._read_event)

    def recvfrom(self, *args):
        while True:
            try:
                return _socket.socket.recvfrom(self._sock, *args)
            except error as ex:
                if ex.args[0] != EWOULDBLOCK or self.timeout == 0.0:
                    raise

            self._wait(self._read_event)

    def recvfrom_into(self, *args):
        while True:
            try:
                return _socket.socket.recvfrom_into(self._sock, *args)
            except error as ex:
                if ex.args[0] != EWOULDBLOCK or self.timeout == 0.0:
                    raise

            self._wait(self._read_event)

    def recv_into(self, *args):
        while True:
            try:
                return _socket.socket.recv_into(self._sock, *args)
            except error as ex:
                if ex.args[0] != EWOULDBLOCK or self.timeout == 0.0:
                    raise

            self._wait(self._read_event)

    def send(self, data, flags=0, timeout=timeout_default):
        if timeout is timeout_default:
            timeout = self.timeout
        try:
            return _socket.socket.send(self._sock, data, flags)
        except error as ex:
            if ex.args[0] != EWOULDBLOCK or timeout == 0.0:
                raise
            self._wait(self._write_event)
            try:
                return _socket.socket.send(self._sock, data, flags)
            except error as ex2:
                if ex2.args[0] == EWOULDBLOCK:
                    return 0
                raise

    def sendall(self, data, flags=0):
        data_memory = _get_memory(data)
        len_data_memory = len(data_memory)
        if not len_data_memory:
            return 0
        if self.timeout is None:
            data_sent = 0
            while data_sent < len_data_memory:
                data_sent += self.send(data_memory[data_sent:], flags)

        else:
            timeleft = self.timeout
            end = time.time() + timeleft
            data_sent = 0
            while 1:
                data_sent += self.send(data_memory[data_sent:], flags, timeout=timeleft)
                if data_sent >= len_data_memory:
                    break
                timeleft = end - time.time()
                if timeleft <= 0:
                    raise timeout("timed out")

    def sendto(self, *args):
        try:
            return _socket.socket.sendto(self._sock, *args)
        except error as ex:
            if ex.args[0] != EWOULDBLOCK or self.timeout == 0.0:
                raise
            self._wait(self._write_event)
            try:
                return _socket.socket.sendto(self._sock, *args)
            except error as ex2:
                if ex2.args[0] == EWOULDBLOCK:
                    return 0
                raise

    if hasattr(_socket.socket, "sendmsg"):

        def sendmsg(self, buffers, ancdata=(), flags=0, address=None):
            try:
                return _socket.socket.sendmsg(
                    self._sock, buffers, ancdata, flags, address
                )
            except error as ex:
                if flags & getattr(_socket, "MSG_DONTWAIT", 0):
                    raise
                if ex.args[0] != EWOULDBLOCK or self.timeout == 0.0:
                    raise
                self._wait(self._write_event)
                try:
                    return _socket.socket.sendmsg(
                        self._sock, buffers, ancdata, flags, address
                    )
                except error as ex2:
                    if ex2.args[0] == EWOULDBLOCK:
                        return 0
                    raise

    def setblocking(self, flag):
        if flag:
            self.timeout = None
        else:
            self.timeout = 0.0

    def settimeout(self, howlong):
        if howlong is not None:
            try:
                f = howlong.__float__
            except AttributeError:
                raise TypeError("a float is required")

            howlong = f()
            if howlong < 0.0:
                raise ValueError("Timeout value out of range")
        self.__dict__["timeout"] = howlong

    def gettimeout(self):
        return self.__dict__["timeout"]

    def shutdown(self, how):
        if how == 0:
            self.hub.cancel_wait(self._read_event, cancel_wait_ex)
        else:
            if how == 1:
                self.hub.cancel_wait(self._write_event, cancel_wait_ex)
            else:
                self.hub.cancel_wait(self._read_event, cancel_wait_ex)
                self.hub.cancel_wait(self._write_event, cancel_wait_ex)
            self._sock.shutdown(how)

    def _sendfile_use_sendfile(self, file, offset=0, count=None):
        raise __socket__._GiveupOnSendfile()

    def _sendfile_use_send(self, file, offset=0, count=None):
        self._check_sendfile_params(file, offset, count)
        if self.gettimeout() == 0:
            raise ValueError("non-blocking sockets are not supported")
        if offset:
            file.seek(offset)
        blocksize = min(count, 8192) if count else 8192
        total_sent = 0
        file_read = file.read
        sock_send = self.send
        try:
            while True:
                if count:
                    blocksize = min(count - total_sent, blocksize)
                    if blocksize <= 0:
                        break
                data = memoryview(file_read(blocksize))
                if not data:
                    break
                while True:
                    try:
                        sent = sock_send(data)
                    except BlockingIOError:
                        continue

                    total_sent += sent
                    if sent < len(data):
                        data = data[sent:]
                    else:
                        break

            return total_sent
        finally:
            if total_sent > 0 and hasattr(file, "seek"):
                file.seek(offset + total_sent)

    def _check_sendfile_params(self, file, offset, count):
        if "b" not in getattr(file, "mode", "b"):
            raise ValueError("file should be opened in binary mode")
        if not self.type & SOCK_STREAM:
            raise ValueError("only SOCK_STREAM type sockets are supported")
        if count is not None:
            if not isinstance(count, int):
                raise TypeError(
                    ("count must be a positive integer (got {!r})").format(count)
                )
            if count <= 0:
                raise ValueError(
                    ("count must be a positive integer (got {!r})").format(count)
                )

    def sendfile(self, file, offset=0, count=None):
        """sendfile(file[, offset[, count]]) -> sent
        
        Send a file until EOF is reached by using high-performance
        os.sendfile() and return the total number of bytes which
        were sent.
        *file* must be a regular file object opened in binary mode.
        If os.sendfile() is not available (e.g. Windows) or file is
        not a regular file socket.send() will be used instead.
        *offset* tells from where to start reading the file.
        If specified, *count* is the total number of bytes to transmit
        as opposed to sending the file until EOF is reached.
        File position is updated on return or also in case of error in
        which case file.tell() can be used to figure out the number of
        bytes which were sent.
        The socket must be of SOCK_STREAM type.
        Non-blocking sockets are not supported.
        
        .. versionadded:: 1.1rc4
           Added in Python 3.5, but available under all Python 3 versions in
           gevent.
        """
        return self._sendfile_use_send(file, offset, count)

    if hasattr(os, "get_inheritable") or hasattr(os, "get_handle_inheritable"):
        if os.name == "nt":

            def get_inheritable(self):
                return os.get_handle_inheritable(self.fileno())

            def set_inheritable(self, inheritable):
                os.set_handle_inheritable(self.fileno(), inheritable)

        else:

            def get_inheritable(self):
                return os.get_inheritable(self.fileno())

            def set_inheritable(self, inheritable):
                os.set_inheritable(self.fileno(), inheritable)

        _added = "\n\n.. versionadded:: 1.1rc4 Added in Python 3.4"
        get_inheritable.__doc__ = "Get the inheritable flag of the socket" + _added
        set_inheritable.__doc__ = "Set the inheritable flag of the socket" + _added
        del _added


if sys.version_info[:2] == (3, 4) and sys.version_info[:3] <= (3, 4, 2):
    SocketType = __socket__.SocketType
    if "SocketType" in __implements__:
        __implements__.remove("SocketType")
    if "SocketType" not in __imports__:
        __imports__.append("SocketType")
    else:
        SocketType = socket

    def fromfd(fd, family, type, proto=0):
        """ fromfd(fd, family, type[, proto]) -> socket object
        
        Create a socket object from a duplicate of the given file
        descriptor.  The remaining arguments are the same as for socket().
        """
        nfd = dup(fd)
        return socket(family, type, proto, nfd)

    if hasattr(_socket.socket, "share"):

        def fromshare(info):
            """ fromshare(info) -> socket object
            
            Create a socket object from a the bytes object returned by
            socket.share(pid).
            """
            return socket(0, 0, 0, info)

        __implements__.append("fromshare")
    if hasattr(_socket, "socketpair"):

        def socketpair(family=None, type=SOCK_STREAM, proto=0):
            """socketpair([family[, type[, proto]]]) -> (socket object, socket object)
            
            Create a pair of socket objects from the sockets returned by the platform
            socketpair() function.
            The arguments are the same as for socket() except the default family is
            AF_UNIX if defined on the platform; otherwise, the default is AF_INET.
            
            .. versionchanged:: 1.2
               All Python 3 versions on Windows supply this function (natively
               supplied by Python 3.5 and above).
            """
            if family is None:
                try:
                    family = AF_UNIX
                except NameError:
                    family = AF_INET

                a, b = _socket.socketpair(family, type, proto)
                a = socket(family, type, proto, a.detach())
                b = socket(family, type, proto, b.detach())
                return (a, b)

    else:
        _LOCALHOST = "127.0.0.1"
        _LOCALHOST_V6 = "::1"

        def socketpair(family=AF_INET, type=SOCK_STREAM, proto=0):
            if family == AF_INET:
                host = _LOCALHOST
            else:
                if family == AF_INET6:
                    host = _LOCALHOST_V6
                else:
                    raise ValueError(
                        "Only AF_INET and AF_INET6 socket address families are supported"
                    )
                if type != SOCK_STREAM:
                    raise ValueError("Only SOCK_STREAM socket type is supported")
                if proto != 0:
                    raise ValueError("Only protocol zero is supported")
                lsock = socket(family, type, proto)
                try:
                    lsock.bind((host, 0))
                    lsock.listen(128)
                    addr, port = lsock.getsockname()[:2]
                    csock = socket(family, type, proto)
                    try:
                        csock.setblocking(False)
                        try:
                            csock.connect((addr, port))
                        except (BlockingIOError, InterruptedError):
                            pass

                        csock.setblocking(True)
                        ssock, _ = lsock.accept()
                    except:
                        csock.close()
                        raise

                finally:
                    lsock.close()

                return (ssock, csock)

        if sys.version_info[:2] < (3, 5):
            if "socketpair" in __implements__:
                __implements__.remove("socketpair")

    def _do_reuse_or_drop(sock, methname):
        try:
            method = getattr(sock, methname)
        except (AttributeError, TypeError):
            pass
        else:
            method()

    from io import BytesIO

    class _basefileobject(object):
        """Faux file object attached to a socket object."""

        default_bufsize = 8192
        name = "<socket>"
        __slots__ = [
            "mode",
            "bufsize",
            "softspace",
            "_sock",
            "_rbufsize",
            "_wbufsize",
            "_rbuf",
            "_wbuf",
            "_wbuf_len",
            "_close",
        ]

        def __init__(self, sock, mode="rb", bufsize=-1, close=False):
            _do_reuse_or_drop(sock, "_reuse")
            self._sock = sock
            self.mode = mode
            if bufsize < 0:
                bufsize = self.default_bufsize
            self.bufsize = bufsize
            self.softspace = False
            if bufsize == 0:
                self._rbufsize = 1
            else:
                if bufsize == 1:
                    self._rbufsize = self.default_bufsize
                else:
                    self._rbufsize = bufsize
                self._wbufsize = bufsize
                self._rbuf = BytesIO()
                self._wbuf = []
                self._wbuf_len = 0
                self._close = close

        def _getclosed(self):
            return self._sock is None

        closed = property(_getclosed, doc="True if the file is closed")

        def close(self):
            try:
                if self._sock:
                    self.flush()
            finally:
                s = self._sock
                self._sock = None
                if s is not None:
                    if self._close:
                        s.close()
                    else:
                        _do_reuse_or_drop(s, "_drop")

        def __del__(self):
            try:
                self.close()
            except:
                pass

        def flush(self):
            if self._wbuf:
                data = (b"").join(self._wbuf)
                self._wbuf = []
                self._wbuf_len = 0
                buffer_size = max(self._rbufsize, self.default_bufsize)
                data_size = len(data)
                write_offset = 0
                view = memoryview(data)
                try:
                    while write_offset < data_size:
                        self._sock.sendall(
                            view[write_offset : write_offset + buffer_size]
                        )
                        write_offset += buffer_size

                finally:
                    if write_offset < data_size:
                        remainder = data[write_offset:]
                        del view
                        del data
                        self._wbuf.append(remainder)
                        self._wbuf_len = len(remainder)

        def fileno(self):
            return self._sock.fileno()

        def write(self, data):
            if not isinstance(data, bytes):
                raise TypeError("Non-bytes data")
            if not data:
                return
            self._wbuf.append(data)
            self._wbuf_len += len(data)
            if (
                self._wbufsize == 0
                or self._wbufsize == 1
                and b"\n" in data
                or self._wbufsize > 1
                and self._wbuf_len >= self._wbufsize
            ):
                self.flush()

        def writelines(self, list):
            lines = filter(None, map(str, list))
            self._wbuf_len += sum(map(len, lines))
            self._wbuf.extend(lines)
            if self._wbufsize <= 1 or self._wbuf_len >= self._wbufsize:
                self.flush()

        def read(self, size=-1):
            rbufsize = max(self._rbufsize, self.default_bufsize)
            buf = self._rbuf
            buf.seek(0, 2)
            if size < 0:
                self._rbuf = BytesIO()
                while True:
                    try:
                        data = self._sock.recv(rbufsize)
                    except InterruptedError:
                        continue

                    if not data:
                        break
                    buf.write(data)

                return buf.getvalue()
            else:
                buf_len = buf.tell()
                if buf_len >= size:
                    buf.seek(0)
                    rv = buf.read(size)
                    self._rbuf = BytesIO()
                    self._rbuf.write(buf.read())
                    return rv
                self._rbuf = BytesIO()
                while 1:
                    left = size - buf_len
                    try:
                        data = self._sock.recv(left)
                    except InterruptedError:
                        continue

                    if not data:
                        break
                    n = len(data)
                    if n == size:
                        if not buf_len:
                            return data
                        if n == left:
                            buf.write(data)
                            del data
                            break
                        if not n <= left:
                            raise AssertionError(
                                "recv(%d) returned %d bytes" % (left, n)
                            )
                        buf.write(data)
                        buf_len += n
                        del data

                return buf.getvalue()

        def readline(self, size=-1):
            buf = self._rbuf
            buf.seek(0, 2)
            if buf.tell() > 0:
                buf.seek(0)
                bline = buf.readline(size)
                if bline.endswith(b"\n") or len(bline) == size:
                    self._rbuf = BytesIO()
                    self._rbuf.write(buf.read())
                    return bline
                del bline
            if size < 0:
                if self._rbufsize <= 1:
                    buf.seek(0)
                    buffers = [buf.read()]
                    self._rbuf = BytesIO()
                    data = None
                    recv = self._sock.recv
                    while True:
                        try:
                            while data != b"\n":
                                data = recv(1)
                                if not data:
                                    break
                                buffers.append(data)

                        except InterruptedError:
                            continue

                        break

                    return (b"").join(buffers)
                buf.seek(0, 2)
                self._rbuf = BytesIO()
                while True:
                    try:
                        data = self._sock.recv(self._rbufsize)
                    except InterruptedError:
                        continue

                    if not data:
                        break
                    nl = data.find(b"\n")
                    if nl >= 0:
                        nl += 1
                        buf.write(data[:nl])
                        self._rbuf.write(data[nl:])
                        del data
                        break
                    buf.write(data)

                return buf.getvalue()
            else:
                buf.seek(0, 2)
                buf_len = buf.tell()
                if buf_len >= size:
                    buf.seek(0)
                    rv = buf.read(size)
                    self._rbuf = BytesIO()
                    self._rbuf.write(buf.read())
                    return rv
                self._rbuf = BytesIO()
                while 1:
                    try:
                        data = self._sock.recv(self._rbufsize)
                    except InterruptedError:
                        continue

                    if not data:
                        break
                    left = size - buf_len
                    nl = data.find(b"\n", 0, left)
                    if nl >= 0:
                        nl += 1
                        self._rbuf.write(data[nl:])
                        if buf_len:
                            buf.write(data[:nl])
                            break
                        else:
                            return data[:nl]
                        n = len(data)
                        if n == size:
                            if not buf_len:
                                return data
                            if n >= left:
                                buf.write(data[:left])
                                self._rbuf.write(data[left:])
                                break
                            buf.write(data)
                        buf_len += n

                return buf.getvalue()

        def readlines(self, sizehint=0):
            total = 0
            list = []
            while 1:
                line = self.readline()
                if not line:
                    break
                list.append(line)
                total += len(line)
                if sizehint:
                    if total >= sizehint:
                        break

            return list

        def __iter__(self):
            return self

        def next(self):
            line = self.readline()
            if not line:
                raise StopIteration
            return line

        __next__ = next

    try:
        from gevent.fileobject import FileObjectPosix
    except ImportError:
        _fileobject = _basefileobject
    else:

        class _fileobject(FileObjectPosix):
            def __init__(self, sock, mode="rb", bufsize=-1, close=False):
                _do_reuse_or_drop(sock, "_reuse")
                self._sock = sock
                FileObjectPosix.__init__(self, sock, mode, bufsize, close)

            def close(self):
                try:
                    if self._sock:
                        self.flush()
                finally:
                    s = self._sock
                    self._sock = None
                    if s is not None:
                        if self._close:
                            FileObjectPosix.close(self)
                        else:
                            _do_reuse_or_drop(s, "_drop")

            def __del__(self):
                try:
                    self.close()
                except:
                    pass

    __all__ = __implements__ + __extensions__ + __imports__
